//
// Created by DELL on 2024/2/29.
//
#include <iostream>
#include <atomic>
#include <thread>
#include <vector>
#include <barrier>

class SpinLock
{
public:

    void lock()
    {
        bool expected = false;
        while (!isLock.compare_exchange_weak(expected, true, std::memory_order_acquire, std::memory_order_relaxed))
        {
            expected = false;
        }
    }

    void unlock()
    {
        isLock.store(false, std::memory_order_release);
    }

private:
    std::atomic<bool> isLock{false};
};

class SpinLock2
{
public:

    void lock()
    {
        while (flag.test_and_set(std::memory_order_acquire))
        {
#if _HAS_CXX20
            // 失败时使用 relaxed ， 需要C++ 20, C++20 增加了 test 函数
            while (flag.test(std::memory_order_relaxed))
            {

            }
#endif // _HAS_CXX20
        }
    }

    void unlock()
    {
        flag.clear(std::memory_order_release);
    }

private:
    std::atomic_flag flag = ATOMIC_FLAG_INIT;
};


int main()
{
    std::vector<std::thread> threads;
    threads.resize(std::thread::hardware_concurrency());
    SpinLock lock;
//    SpinLock2 lock;

    std::barrier barrier(threads.size());

    int n = 0;
    int count = 10000;
    auto work = [&n, count, &lock, &barrier](){
        barrier.arrive_and_wait();
        for (int i = 0; i < count; ++i)
        {
            lock.lock();
            ++n;
            lock.unlock();
        }
    };
    for (auto& thread : threads)
    {
        thread = std::thread(work);
    }

    for (auto& thread : threads)
    {
        thread.join();
    }

    std::cout << "Desired Count: " << count * std::thread::hardware_concurrency() << std::endl;
    std::cout << "num: " << n << std::endl;

    return 0;
}
